//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Windows;
using System.Windows.Input;
using OpenLS.Spreadsheet.UI.Internals;

namespace OpenLS.Spreadsheet.UI
{
    internal static class GridCommandHelper
    {
        #region Nested type: MultiAction

        public delegate void MultiAction<T1, T2>(T1 t1, T2 t2);

        public delegate void MultiAction<T1, T2, T3>(T1 t1, T2 t2, T3 t3);

        #endregion

        private static void processRepeatableCommand(object sender, ExecutedRoutedEventArgs args,
                                           MultiAction<Worksheet, object> action)
        {
            Worksheet worksheet = getWorksheet(sender);
            SetLastExecutedCommand(sender, args);
            action(worksheet, args.Parameter);
            args.Handled = true;
        }
        private static void processCommand(object sender, ExecutedRoutedEventArgs args,
                                           MultiAction<Worksheet, object> action)
        {
            Worksheet worksheet = getWorksheet(sender);
            action(worksheet, args.Parameter);
            args.Handled = true;
        }
        private static void processCommand(object sender, ExecutedRoutedEventArgs args,
                                           MultiAction<object, Worksheet, object> action)
        {
            Worksheet worksheet = getWorksheet(sender);
            action(sender, worksheet, args.Parameter);
            args.Handled = true;
        }

        private static void processCommand(object sender, ExecutedRoutedEventArgs args,
                                           Action<Worksheet> action)
        {
            Worksheet worksheet = getWorksheet(sender);
            action(worksheet);
            args.Handled = true;
        }
        private static void processRepeatableCommand(object sender, ExecutedRoutedEventArgs args,
                                           MultiAction<object, Worksheet, object> action)
        {
            Worksheet worksheet = getWorksheet(sender);
            SetLastExecutedCommand(sender, args);
            action(sender, worksheet, args.Parameter);
            args.Handled = true;
        }

        internal static void SetLastExecutedCommand(object sender, ExecutedRoutedEventArgs args)
        {
            SetLastExecutedCommand(sender, new ExecutedCommand((RoutedCommand)args.Command, args.Parameter));
        }
        internal static void SetLastExecutedCommand(object sender, ExecutedCommand executedCommand)
        {
            DependencyObject root = EditionElement.GetEditorRoot((DependencyObject)sender);
            EditionElement.SetLastExecutedCommand(root,
                                                  executedCommand);
        }


        private static Worksheet getWorksheet(object sender)
        {
            return WorksheetHelper.GetWorksheet(sender);
        }
        private static void addAnyCommandBinding(UIElement g, RoutedCommand command,
                                                        ExecutedRoutedEventHandler execute,
                                                        CanExecuteRoutedEventHandler canExecute)
        {
            g.CommandBindings.Add(new CommandBinding(command,
                                                     execute, canExecute));
        }

        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<Worksheet, object> action,
                                                                CanExecuteRoutedEventHandler canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processRepeatableCommand(sender, args, action)
                                        , canExecute);
        }
        static void AddWorksheetCommand(UIElement g, ICommand command, Action<Worksheet> onExecute, Func<Worksheet, bool> onCanExecute)
        {
            g.CommandBindings.Add(new CommandBinding(command, (sender, args) =>
            {
                onExecute
                    (getWorksheet
                         (sender));
                args.Handled = true;
            },
                                                     (sender, args) =>
                                                     {
                                                         args.CanExecute = onCanExecute(getWorksheet(sender));
                                                         args.Handled = true;
                                                     }));
        }
        static void AddWorksheetCommand(UIElement g, ICommand command, ExecutedRoutedEventHandler onExecute, Func<Worksheet, bool> onCanExecute)
        {
            g.CommandBindings.Add(new CommandBinding(command, onExecute,
                                                     (sender, args) =>
                                                     {
                                                         args.CanExecute = onCanExecute(getWorksheet(sender));
                                                         args.Handled = true;
                                                     }));
        }

        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<Worksheet, object> action,
                                                                Func<Worksheet, bool> canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processRepeatableCommand(sender, args, action)
                                        , (sender, args) => { args.CanExecute = canExecute(getWorksheet(sender));
                                                                args.Handled = true; });
        }

        public static void AddWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<Worksheet, object> action,
                                                                CanExecuteRoutedEventHandler canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processCommand(sender, args, action)
                                        , canExecute);
        }
        public static void AddWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<Worksheet, object> action,
                                                                Func<Worksheet, bool> canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processCommand(sender, args, action)
                                        , (sender, args) => { args.CanExecute = canExecute(getWorksheet(sender));
                                                                args.Handled = true; });
        }

        public static void AddWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                        MultiAction<object, Worksheet, object> action,
                                                        CanExecuteRoutedEventHandler canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processCommand(sender, args, action)
                                        , canExecute);
        }
        public static void AddWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                        MultiAction<object, Worksheet, object> action,
                                                        Func<Worksheet, bool> canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processCommand(sender, args, action)
                                        , (sender, args) => { args.CanExecute = canExecute(getWorksheet(sender));
                                                                args.Handled = true;}) ;
        }
        public static void AddWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                        Action<Worksheet> action,
                                                        Func<Worksheet, bool> canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processCommand(sender, args, action)
                                        , (sender, args) =>
                                        {
                                            args.CanExecute = canExecute(getWorksheet(sender));
                                            args.Handled = true;
                                        });
        }
        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<object, Worksheet, object> action,
                                                                CanExecuteRoutedEventHandler canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processRepeatableCommand(sender, args, action)
                                        , canExecute);
        }
        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                MultiAction<object, Worksheet, object> action,
                                                                Func<Worksheet, bool> canExecute)
        {
            addAnyCommandBinding(g, command,
                                        (sender, args) => processRepeatableCommand(sender, args, action)
                                        , (sender, args) => { args.CanExecute = canExecute(getWorksheet(sender));
                                                                args.Handled = true; });
        }
        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                       MultiAction<object, Worksheet, object> action)
        {
            AddRepeatableWorksheetCommandBinding(g, command, action, (sender, args) => {
                                                                                           WorksheetHelper.OnHasSelection(sender, args);
            });
        }
        public static void AddRepeatableWorksheetCommandBinding(UIElement g, RoutedCommand command,
                                                                       MultiAction<Worksheet, object> action)
        {
            AddRepeatableWorksheetCommandBinding(g, command, action, (sender, args) => {
                                                                                           WorksheetHelper.OnHasSelection(sender, args);
            });
        }



        
    }
}